﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Threading;
using FacebookWrapper.ObjectModel;

namespace Desktop_Facebook
{
    public class FetchInfo
    {
		public enum eTables 
		{ 
			FriendInteractionStatistics,
			Birthdays, 
			Inbox, 
			Events 
		}

        public delegate void UpdateProgressBar();
        
		public delegate void InitProgressBar(int i_MinValue, int i_MaxValue);
		
		public delegate void UpdateStatusBar(bool i_Status);
        
		public event UpdateProgressBar ProgressBarUpdater;
        
		public event InitProgressBar ProgressBarInitiator;
		
		public event UpdateStatusBar StatusBarUpdater;

		public event Action<DataTable, eTables> NotifyTableReady;
		
        public DataTable FriendInteractionStatisticsTable { get; set; }

        public DataTable EventsTable { get; set; }

        public DataTable BirthdaysTable { get; set; }

        public DataTable InboxTable { get; set; }

		public FriendScoreGenerator FriendScoreGenerator
		{
			get { return r_FriendScoreGenerator; }
		}

		public BirthdayHolder BirthdayHolder 
        { 
            get { return r_BirthdayHolder; } 
        }

		private readonly BirthdayHolder r_BirthdayHolder = new BirthdayHolder();

		private readonly FriendScoreGenerator r_FriendScoreGenerator = new FriendScoreGenerator();

		private const bool v_CheckedRow = true;
		private const bool v_Working = true;

		public void GetAll()
		{
			Thread[] threads = new Thread[4];

			threads[0] = new Thread(new ThreadStart(new Action(() =>
			{
				GenerateFriendInteractionStatistics();
				NotifyTableReady.Invoke(FriendInteractionStatisticsTable, eTables.FriendInteractionStatistics);
			})));

			threads[1] = new Thread(new ThreadStart(new Action(() =>
			{
				GetEvents();
				NotifyTableReady.Invoke(EventsTable, eTables.Events);
			})));

			threads[2] = new Thread(new ThreadStart(new Action(() =>
			{
				GetBirthdays();
				NotifyTableReady.Invoke(BirthdaysTable, eTables.Birthdays);
			})));

			threads[3] = new Thread(new ThreadStart(new Action(() =>
			{
				GetInbox();
				NotifyTableReady.Invoke(InboxTable, eTables.Inbox);
			})));

			foreach (Thread thread in threads)
			{
				thread.Start();
			}			
		}

        public void GenerateFriendInteractionStatistics()
        {
			StatusBarUpdater(v_Working);

			DataTable table = new DataTable();
            table.Columns.Add("Friend", typeof(object));
			table.Columns.Add("Name", typeof(string));
			table.Columns.Add("Points", typeof(int));

            FriendScoreGenerator.GenerateScores();

            ProgressBarInitiator(0, Session.Instance.LoggedInUser.Friends.Count);
            foreach (User currentFriend in Session.Instance.LoggedInUser.Friends)
            {
                table.Rows.Add(
					currentFriend, 
					currentFriend.Name, 
					FriendScoreGenerator.Scores[currentFriend.Id].Score);
                ProgressBarUpdater();
            }

			FriendInteractionStatisticsTable = table;
			StatusBarUpdater(!v_Working);
        }

        public void GetEvents()
        {
			StatusBarUpdater(v_Working);

			DataTable table = new DataTable();
			table.Columns.Add("Event", typeof(object));
			table.Columns.Add("Selected", typeof(bool));
			table.Columns.Add("Date", typeof(DateTime));
			table.Columns.Add("Event Name", typeof(string));
			table.Columns.Add("Owner", typeof(string));
			table.Columns.Add("Location", typeof(string));

            ProgressBarInitiator(0, Session.Instance.LoggedInUser.Events.Count);
            foreach (Event currentEvent in Session.Instance.LoggedInUser.Events)
            {
				table.Rows.Add(
					currentEvent, 
					!v_CheckedRow, 
					currentEvent.StartTime, 
					currentEvent.Name,
					currentEvent.Owner.Name, 
					currentEvent.Location);
                ProgressBarUpdater();
            }

			EventsTable = table;
			StatusBarUpdater(!v_Working);
        }

        public void GetBirthdays()
        {
			StatusBarUpdater(v_Working);
			DataTable table = new DataTable();

			table.Columns.Add("Birthday", typeof(object));
			table.Columns.Add("Selected", typeof(bool));
			table.Columns.Add("Name", typeof(string));
			table.Columns.Add("Date", typeof(CustomDate));

            r_BirthdayHolder.MakeBirthdays();

            ProgressBarInitiator(0, Session.Instance.LoggedInUser.Friends.Count);
            foreach (User currentFriend in Session.Instance.LoggedInUser.Friends)
            {
                if (r_BirthdayHolder.Birthdays.ContainsKey(currentFriend.Id))
                {
					table.Rows.Add(
						currentFriend,
						!v_CheckedRow, 
						currentFriend.Name,
						r_BirthdayHolder.Birthdays[currentFriend.Id]);
                    ProgressBarUpdater();
                }
            }

			BirthdaysTable = table;
			StatusBarUpdater(!v_Working);
        }

        public void GetInbox()
        {
			StatusBarUpdater(v_Working);
            List<Message> filter = new MessageFilterer().FilterByPredicate((message) => true);
            PopulateInboxDataTable(filter);
			StatusBarUpdater(!v_Working);
        }

        public void PopulateInboxDataTable(List<Message> i_Messages)
        {
			DataTable table = new DataTable();

			table.Columns.Add("InboxMessage", typeof(object));
			table.Columns.Add("Selected", typeof(bool));
			table.Columns.Add("From", typeof(string));
			table.Columns.Add("Message", typeof(string));
			table.Columns.Add("Date", typeof(DateTime));

            ProgressBarInitiator(0, i_Messages.Count);
            foreach (Message currentMessage in i_Messages)
            {
                if (currentMessage.From != null)
                {
					table.Rows.Add(
						currentMessage, 
						!v_CheckedRow, 
						currentMessage.From.Name, 
						currentMessage.Text, 
						currentMessage.CreatedTime);
					ProgressBarUpdater();
                }
            }

			InboxTable = table;
        }
    }
}
